package com.binary.coder.gift.core.config;

import com.binary.coder.gift.core.common.bean.BizException;
import com.binary.coder.gift.core.common.bean.ResultBean;
import com.binary.coder.gift.core.common.constant.FailCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.stream.Collectors;

/**
 * @author qinqin.luo.
 * @title
 * @time 2022/5/7.
 */
@RestControllerAdvice(basePackages = "com.cisdi.colmet")
@Slf4j
public class GlobalHandler implements RequestBodyAdvice {

    @ExceptionHandler(BizException.class)
    @ResponseBody
    public ResultBean handleBizException(BizException e) {
        log.error("GlobalHandler bizException:", e);
        ResultBean resultBean = ResultBean.failed();
        resultBean.setMessage(e.getMessage());
        return resultBean;
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResultBean handleCommonException(Exception e) {
        log.error("GlobalHandler exception:", e);
        if (e instanceof MethodArgumentNotValidException) {
            String message = ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
            return ResultBean.failed(message);
        }
        return ResultBean.failed(FailCodeEnum.CODE_500.getDesc(), FailCodeEnum.CODE_500.getCode());
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ResultBean constraintViolationExceptionHandler(ConstraintViolationException e) {
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        return ResultBean.failed(message);
    }

    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        //保留 排查请求不能序列化
        return httpInputMessage;
    }

    @Override
    public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return o;
    }

    @Override
    public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return o;
    }
}
